package com.ntty.server.handle;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;

import com.ntty.utils.FileTools;


import hyl.core.Amy;
import hyl.core.MyDate;
import hyl.core.MyFun;
import hyl.core.conf.MyConst;
import hyl.core.io.MyFile;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.DiskAttribute;
import io.netty.handler.codec.http.multipart.DiskFileUpload;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.HttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
import io.netty.util.ReferenceCountUtil;

import java.net.SocketAddress;
import java.net.URI;

public class HttpUpLoadFileHandler extends SimpleChannelInboundHandler<HttpObject> {

	private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); // Disk
																												// if
																												// size
	private boolean readingChunks; // exceed
	
	private static final String URI = "/upload";
	private HttpPostRequestDecoder httpDecoder;
	HttpRequest request;
	static {
		DiskFileUpload.deleteOnExitTemporaryFile = true; // should delete file
															// on exit (in normal
															// exit)
		DiskFileUpload.baseDirectory = null; // system temp directory
		DiskAttribute.deleteOnExitTemporaryFile = true; // should delete file on
														// exit (in normal exit)
		DiskAttribute.baseDirectory = null; // system temp directory
	}
	final String FAVICON_ICO = "/favicon.ico";
	String classpath;
	String savepath;
	String downpath;

	/**
	 * 一个完整的HttpRequest请求<br>
	 * HTTP Request 第一部分是包含的头信息<br>
	 * HttpContent 里面包含的是数据，可以后续有多个 HttpContent 部分<br>
	 * LastHttpContent 标记是 HTTP request 的结束，同时可能包含头的尾部信息<br>
	 * 
	 * 一个完整的HttpResponse请求<br>
	 * HTTP response 第一部分是包含的头信息<br>
	 * HttpContent 里面包含的是数据，可以后续有多个 HttpContent 部分<br>
	 * LastHttpContent 标记是 HTTP response 的结束，同时可能包含头的尾部信息<br>
	 */
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, HttpObject httpObject) throws Exception {
		if (httpObject instanceof HttpRequest) {
			request = (HttpRequest) httpObject;
			URI uri = new URI(request.uri());
			String path = uri.getPath();
			if (path.equals(FAVICON_ICO)) {
				return;
			}

			// 上传
			if (request.uri().startsWith(URI) && request.method().equals(HttpMethod.POST)) {

				classpath = FileTools.getPath("f");
				savepath = FileTools.getUploadPath() + classpath;
				downpath = FileTools.getBasePath(ctx) + "down?f=" + classpath;
				MyFile.openDir(savepath);
				System.out.println(1 + path + request.method());
				if (httpDecoder != null) {
					httpDecoder.cleanFiles();
					httpDecoder = null;
				}
				httpDecoder = new HttpPostRequestDecoder(factory, request);

				// httpDecoder.setDiscardThreshold(0);
			} else {
				// 传递给下一个Handler
				ctx.fireChannelRead(httpObject);
			}
		}
		if (httpDecoder != null && httpObject instanceof HttpContent) {

			HttpContent chunk = (HttpContent) httpObject;
			// System.out.println(chunk.content().toString());
			httpDecoder.offer(chunk);

			writeChunk(ctx);
			if (chunk instanceof LastHttpContent) {

				readingChunks = false;
				// 关闭httpDecoder
				httpDecoder.destroy();
				httpDecoder = null;
			}
			ReferenceCountUtil.release(httpObject);
		}
		/*
		 * } else { ctx.fireChannelRead(httpObject); }
		 */
	}

	private void writeChunk(ChannelHandlerContext ctx) {

		while (httpDecoder.hasNext()) {

			InterfaceHttpData data = httpDecoder.next();
			if (data != null) {
				if (data.getHttpDataType() == HttpDataType.Attribute) {
				} else if (data.getHttpDataType() == HttpDataType.InternalAttribute) {
				} else {
					System.out.println(6);
					{
						
						FileUpload fileUpload = (FileUpload) data;
						String oldfilename = fileUpload.getFilename();
						String fname = FileTools.getNewName(oldfilename);
						Map<String,Object> fileinfo=new HashMap<>();
						File newfile;
						// 保存新文件
						try {
							if (!MyFun.isEmpty(fileUpload.getFilename())) {
								
						
							InputStream fis=new FileInputStream(fileUpload.getFile());
							newfile = MyFile.saveFile(fis, savepath, fname);
							fileinfo.put("path", downpath+ newfile.getName());
							fileinfo.put("oldsize", fileUpload.getFile().length());
							fileinfo.put("newsize", newfile.length());
							fileinfo.put("oldname", oldfilename);		
							}
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
			
						}

						/*File file = new File(FILE_UPLOAD + fileUpload.getFilename());
						System.out.println("upload file: {" + fileUpload.getFilename() + "}");
						try (FileChannel inputChannel = new FileInputStream(fileUpload.getFile()).getChannel();
								FileChannel outputChannel = new FileOutputStream(file).getChannel()) {
							outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
						} catch (Exception e) {
							e.printStackTrace();
						}*/
					}
				}
				data.release();
			}
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		Amy.Log.warn("{}", cause);
		ctx.channel().close();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		if (httpDecoder != null) {
			httpDecoder.cleanFiles();
		}
	}

}
